/*
 * Copyright (c) 2019 Winner Microelectronics Co., Ltd.
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2022-11-03     yuanzihao    first implementation
 */

#include <rtthread.h>
#include <rtdevice.h>
#include <fal.h>
#include <drv_ch423.h>
#include <speech_module_thread.h>
#include <ext_gpio_control_thread.h>
#include <work_mode_thread.h>
#include <upacker.h>
#include <aht20_f.h>
#include <ulog.h>
#include "jx_uart_send.h"

extern void CMD_wakeOnLAN(void);

#define UART_NAME "uart1" /* 串口设备名称 */

upacker_inst msg_packer;

/* 用于接收消息的信号量 */
static struct rt_semaphore rx_sem;
static rt_device_t serial;
/* 接收数据回调函数 */

#define THREAD_PRIORITY 25
#define THREAD_STACK_SIZE 512
#define THREAD_TIMESLICE 5

ALIGN(RT_ALIGN_SIZE)
static char speech_module_thread_stack[2048];
static struct rt_thread speech_module_thread;

static rt_timer_t speech_module_timer;
static uint8_t temp_count = 0;

#define TEMP_SENSOR_NAME "temp_aht20_f"
rt_device_t temp_dev;
struct rt_sensor_data temp_data;
#define HUMI_SENSOR_NAME "humi_aht20_f"
rt_device_t humi_dev;
struct rt_sensor_data humi_data;

extern int get_boot_times(void);
// 串口发送函数实现
void _uart_send_impl(unsigned char *buff, int len)
{
    // TODO: 调用项目实际的串口发送函数
    /*
    int i = 0;
    unsigned char c;
    for (i = 0; i < len; i++) {
      c = buff[i];
      printf("%02X ", c);
    }
    printf("\n");
    */
    rt_device_write(serial, 0, buff, len);
}
/**
 * @brief  串口发送接口
 * @note
 * @param  *d:
 * @param  size:
 * @retval None
 */
static void uart_send(uint8_t *d, uint16_t size)
{
    rt_device_write(serial, 0, d, size);
}

/**
 * @brief  消息解析回调
 * @note
 * @param  *d:
 * @param  size:
 * @retval None
 */
static void handle_cb(uint8_t *d, uint16_t size)
{
    time_t timep;
    struct tm *p;
    time(&timep);
    p = localtime(&timep);
    // 接收到payload
    rt_kprintf("pack len%d\n", size);
    switch (d[0])
    {
    case Ctrl_Nixie_Tube:
        // not supported
        break;
    case Change_Work_Mode:
        switch (d[1])
        {
        case Set_To_Pomodoro_Mode:
            set_work_mode(WORK_MODE_POMODORO);
            break;
        case Set_To_Counter_Mode:
            set_work_mode(WORK_MODE_NUM_COUNTER);
            break;
        case Set_To_Show_Time_Mode:
            set_work_mode(WORK_MODE_SHOW_TIME);
            break;
        default:
            log_e(" error Pomodoro ctrl mode %d!", d[1]);
            break;
        }
        break;
    case Computer_Ctrl:
        switch (d[1])
        {
        case Computer_Open:
			CMD_wakeOnLAN();
            break;
        case Computer_Off:
            break;
        default:
            log_e(" error Computer_Ctrl %d!", d[1]);
            break;
        }
        break;
    case Pomodoro_Mode:
        switch (d[1])
        {
        case Pomodoro_Start:
            start_pomodoro_mode();
            break;
        case Pomodoro_Stop:
            stop_pomodoro_mode();
            break;
        default:
            log_e(" error Pomodoro ctrl mode %d!", d[1]);
            break;
        }
        break;
    case Counter_Mode:
        break;
    case Show_Time_Mode:
        break;
    case Multi_speech_mode:
        switch (d[1])
        {
        case Get_Now_Time_Hour_Minute:
            _uart_PlayNowHoursMin(p->tm_hour, p->tm_min);
            break;
        case Get_Now_Time_Years_Months_Days:
            _uart_PlayNowYearsMou(p->tm_year + 1900, p->tm_mon + 1, p->tm_mday, p->tm_wday);
            break;
        case Get_Now_Pomodoro_Finished_Times:
            _uart_PlayPomoCount(get_pomodoro_count());
            break;
        case Get_Boots_Times:
            _uart_PlayBootCount(get_boot_times());
            break;
        case Open_Nixie_Tube:
            open_nixie_tube();
            break;
        case Shut_Nixie_Tube:
            shut_nixie_tube();
            break;
        case Get_Now_Temperature:
            if (rt_device_read(temp_dev, 0, &temp_data, 1) == 1)
            {
                _uart_PlayTemp((char)temp_data.data.temp / 10);
                log_i("temp_data.data.temp is %d\r", temp_data.data.temp / 10);
            }
            break;
        case Get_Now_Humidity:
            if (rt_device_read(humi_dev, 0, &humi_data, 1) == 1)
            {
                _uart_PlayHumi((char)humi_data.data.humi / 10);
                log_i("humi_data.data.humi is %d\r", humi_data.data.humi / 10);
            }
            break;
        case Get_Now_Temperature_Humidity:
            if ((rt_device_read(temp_dev, 0, &temp_data, 1) == 1) && (rt_device_read(humi_dev, 0, &humi_data, 1) == 1))
            {
                _uart_PlayTempHumi((int)temp_data.data.temp / 10, (char)humi_data.data.humi / 10);
                log_i("temp_data.data.temp is %d--", temp_data.data.temp / 10);
                log_i("humi_data.data.humi is %d\r", humi_data.data.humi / 10);
            }
            break;
        default:
            log_e(" error Multi_speech_mode mode %d!", d[1]);
            break;
        }
        break;
    default:
        log_e(" error speech ctrl mode %d!", d[0]);
        break;
    }
}

static rt_err_t uart_input(rt_device_t dev, rt_size_t size)
{
    /* 串口接收到数据后产生中断，调用此回调函数，然后发送接收信号量 */
    rt_sem_release(&rx_sem);
    return RT_EOK;
}

static char ch;
/* 线程 speech_module_thread 入口 */
static void speech_module_entry(void *param)
{
    while (1)
    {
        /* 从串口读取一个字节的数据，没有读取到则等待接收信号量 */
        while (rt_device_read(serial, -1, &ch, 1) != 1)
        {
            /* 阻塞等待接收信号量，等到信号量后再次读取数据 */
            rt_sem_take(&rx_sem, RT_WAITING_FOREVER);
        }
        /* 读取到的数据通过串口错位输出 */
        // ch = ch + 1;
        // rt_device_write(serial, 0, &ch, 1);
        /* 输出给串口控制台 */
        // 丢到packer解析，成功了调用callback
        upacker_unpack(&msg_packer, &ch, 1);
//        rt_kprintf("%0x ", ch);

    }
}

int speech_module_thread_init(void)
{
    /* 查找串口设备 */
    serial = rt_device_find(UART_NAME);
    if (!serial)
    {
        rt_kprintf("find %s failed!\n", UART_NAME);
        return RT_ERROR;
    }
    /* 初始化信号量 */
    rt_sem_init(&rx_sem, "rx_sem", 0, RT_IPC_FLAG_FIFO);
    /* 以读写及中断接收方式打开串口设备 */
    rt_device_open(serial, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
    /* 设置接收回调函数 */
    rt_device_set_rx_indicate(serial, uart_input);

    /* 查找传感器设备 */
    temp_dev = rt_device_find(TEMP_SENSOR_NAME);
    humi_dev = rt_device_find(HUMI_SENSOR_NAME);
    /* 以只读及轮询模式打开传感器设备 */
    rt_device_open(temp_dev, RT_DEVICE_FLAG_RDONLY);
    rt_device_open(humi_dev, RT_DEVICE_FLAG_RDONLY);
    /* 初始化线程 */
    rt_thread_init(&speech_module_thread,
                   "speech_module_thread",
                   speech_module_entry,
                   RT_NULL,
                   &speech_module_thread_stack[0],
                   sizeof(speech_module_thread_stack),
                   THREAD_PRIORITY - 1, THREAD_TIMESLICE);
    rt_thread_startup(&speech_module_thread);
    // init packer
    upacker_init(&msg_packer, handle_cb, uart_send);
    return 0;
}
INIT_APP_EXPORT(speech_module_thread_init);

void show_upacker_data(void)
{
    uint8_t buff[2];
    buff[0] = Computer_Ctrl;
    buff[1] = Computer_Open;
    upacker_pack(&msg_packer, (uint8_t *)buff, 2);
    rt_thread_mdelay(100);
    buff[0] = Computer_Ctrl;
    buff[1] = Computer_Off;
    upacker_pack(&msg_packer, (uint8_t *)buff, 2);
    rt_thread_mdelay(100);
    buff[0] = Multi_speech_mode;
    buff[1] = Get_Now_Time_Hour_Minute;
    upacker_pack(&msg_packer, (uint8_t *)buff, 2);
    rt_thread_mdelay(100);
    buff[0] = Multi_speech_mode;
    buff[1] = Get_Now_Time_Years_Months_Days;
    upacker_pack(&msg_packer, (uint8_t *)buff, 2);
    rt_thread_mdelay(100);
    buff[0] = Multi_speech_mode;
    buff[1] = Get_Now_Pomodoro_Finished_Times;
    upacker_pack(&msg_packer, (uint8_t *)buff, 2);
    rt_thread_mdelay(100);
    buff[0] = Multi_speech_mode;
    buff[1] = Get_Boots_Times;
    upacker_pack(&msg_packer, (uint8_t *)buff, 2);
    rt_thread_mdelay(100);
    buff[0] = Multi_speech_mode;
    buff[1] = Open_Nixie_Tube;
    upacker_pack(&msg_packer, (uint8_t *)buff, 2);
    rt_thread_mdelay(100);
    buff[0] = Multi_speech_mode;
    buff[1] = Shut_Nixie_Tube;
    upacker_pack(&msg_packer, (uint8_t *)buff, 2);
    rt_thread_mdelay(100);
    buff[0] = Multi_speech_mode;
    buff[1] = Get_Now_Temperature;
    upacker_pack(&msg_packer, (uint8_t *)buff, 2);
    rt_thread_mdelay(100);
    buff[0] = Multi_speech_mode;
    buff[1] = Get_Now_Humidity;
    upacker_pack(&msg_packer, (uint8_t *)buff, 2);
    rt_thread_mdelay(100);
    buff[0] = Multi_speech_mode;
    buff[1] = Get_Now_Temperature_Humidity;
    upacker_pack(&msg_packer, (uint8_t *)buff, 2);
    rt_thread_mdelay(100);
}

MSH_CMD_EXPORT(show_upacker_data, show upacker data);
